<?php

namespace App\Services;

use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;

class PasswordPolicyService
{
    /**
     * 获取密码验证规则
     *
     * @return Password
     */
    public function getPasswordRules(): Password
    {
        return Password::min(8)
            ->mixedCase() // 至少包含一个大写和一个小写字母
            ->numbers() // 至少包含一个数字
            ->symbols() // 至少包含一个特殊字符
            ->uncompromised(); // 检查是否在已泄露密码列表中
    }

    /**
     * 验证密码强度
     *
     * @param string $password
     * @return array ['valid' => bool, 'errors' => array]
     */
    public function validatePasswordStrength(string $password): array
    {
        $errors = [];

        if (strlen($password) < 8) {
            $errors[] = '密码长度不能少于8位';
        }

        if (!preg_match('/[a-z]/', $password)) {
            $errors[] = '密码必须包含至少一个小写字母';
        }

        if (!preg_match('/[A-Z]/', $password)) {
            $errors[] = '密码必须包含至少一个大写字母';
        }

        if (!preg_match('/[0-9]/', $password)) {
            $errors[] = '密码必须包含至少一个数字';
        }

        if (!preg_match('/[^a-zA-Z0-9]/', $password)) {
            $errors[] = '密码必须包含至少一个特殊字符';
        }

        // 检查是否包含常见弱密码模式
        $weakPatterns = [
            '/12345/',
            '/password/i',
            '/admin/i',
            '/qwerty/i',
            '/abc123/i',
        ];

        foreach ($weakPatterns as $pattern) {
            if (preg_match($pattern, $password)) {
                $errors[] = '密码不能包含常见的弱密码模式';
                break;
            }
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
        ];
    }

    /**
     * 检查密码是否与历史密码相同
     *
     * @param int $userId
     * @param string $newPassword
     * @param int $historyCount 检查最近N个密码
     * @return bool
     */
    public function isPasswordInHistory(int $userId, string $newPassword, int $historyCount = 5): bool
    {
        // 这里可以扩展为存储密码历史记录
        // 目前仅检查当前密码
        $user = \App\Models\User::find($userId);
        
        if ($user && Hash::check($newPassword, $user->password)) {
            return true;
        }

        return false;
    }

    /**
     * 生成密码强度提示
     *
     * @param string $password
     * @return string
     */
    public function getPasswordStrengthHint(string $password): string
    {
        $strength = 0;
        $hints = [];

        if (strlen($password) >= 8) {
            $strength++;
        } else {
            $hints[] = '密码长度建议至少8位';
        }

        if (preg_match('/[a-z]/', $password) && preg_match('/[A-Z]/', $password)) {
            $strength++;
        } else {
            $hints[] = '建议包含大小写字母';
        }

        if (preg_match('/[0-9]/', $password)) {
            $strength++;
        } else {
            $hints[] = '建议包含数字';
        }

        if (preg_match('/[^a-zA-Z0-9]/', $password)) {
            $strength++;
        } else {
            $hints[] = '建议包含特殊字符';
        }

        if (strlen($password) >= 12) {
            $strength++;
        }

        $levels = ['弱', '中', '较强', '强', '非常强'];
        $level = $levels[min($strength, 4)];

        return $level . (empty($hints) ? '' : '，建议：' . implode('、', $hints));
    }
}

